package com.yqya.springboot.websocket.chat.server;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.yqya.springboot.websocket.chat.constants.MessageConstants;
import com.yqya.springboot.websocket.chat.dto.MessageDTO;

/**
 * 聊天服务端
 *
 * @author Kevin
 * @date 2019-07-07
 */
@Component
@ServerEndpoint("/chat")
public class WebSocketChatServer {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketChatServer.class);

    /**
     * 全部在线会话
     */
    private static Map<String, Session> onlineSessionMap = new ConcurrentHashMap<>();

    /**
     * 客户端打开连接
     */
    @OnOpen
    public void onOpen(Session session) {
        // 添加会话对象
        onlineSessionMap.put(session.getId(), session);
        // 发送信息给所有人，更新在线人数
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setType(MessageConstants.TypeEnum.ENTER.getValue());
        messageDTO.setUsername("");
        messageDTO.setMsg("");
        messageDTO.setOnlineCount(onlineSessionMap.size());
        String msg = JSON.toJSONString(messageDTO);
        sendMessageToAll(msg);
    }

    /**
     * 客户端发送消息
     */
    @OnMessage
    public void onMessage(Session session, String msg) {
        // 获取它的用户名和消息
        MessageDTO message = JSON.parseObject(msg, MessageDTO.class);
        // 发送信息给所有人，更新在线人数
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setType(MessageConstants.TypeEnum.SPEAK.getValue());
        messageDTO.setUsername(message.getUsername());
        messageDTO.setMsg(message.getMsg());
        messageDTO.setOnlineCount(onlineSessionMap.size());
        sendMessageToAll(JSON.toJSONString(messageDTO));
    }

    /**
     * 客户端关闭连接
     */
    @OnClose
    public void onClose(Session session) {
        // 移除会话对象
        onlineSessionMap.remove(session.getId());
        // 发送信息给所有人，更新在线人数
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setType(MessageConstants.TypeEnum.QUIT.getValue());
        messageDTO.setUsername("");
        messageDTO.setMsg("");
        messageDTO.setOnlineCount(onlineSessionMap.size());
        sendMessageToAll(JSON.toJSONString(messageDTO));
    }

    /**
     * 通信发生异常
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("++++++ WebSocketChatServer 通信发生异常", error);
    }

    /**
     * 发送信息给所有人
     *
     * @param msg
     */
    private static void sendMessageToAll(String msg) {
        onlineSessionMap.forEach((id, session) -> {
            try {
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                logger.error("+++++++ WebSocketChatServer::sendMessageToAll 发送信息异常", e);
            }
        });
    }

}
